#pragma once
#include <Windows.h>
#include "freelist.h"

template<class valtype,class invalid_node> 
class map_base
{
	inline int hashCodeINT(int v,int total_size)
	{ 
		if(_cach_key!=v)
		{
			unsigned char* pv=(unsigned char*)&v;
			int result = 17;  
			result = result * 37 + pv[0];  
			result = result * 37 + pv[1];  
			result = result * 37 + pv[2];  
			result = result * 37 + pv[3];

			_cach_key = v;
			_cach_res = result % total_size;
		}
		return _cach_res;  
	}  

	int _cach_key;
	int _cach_res;
public:
	valtype operator[](int id) 
	{
		id=id+1;
		int cd = hashCodeINT(id,_total_size);
		while(_int_keys[cd]!=id && _int_keys[cd]!=0) {
			cd++;
			if(cd>=_total_size)
				cd = cd % _total_size;
		}
		if(_int_keys[cd]==0)
			return _none;
		return _int_values[cd];
	}

	int find(int id)
	{
		id=id+1;
		int cd = hashCodeINT(id,_total_size);
		while(_int_keys[cd]!=id && _int_keys[cd]!=0) {
			cd++;
			if(cd>=_total_size)
				cd = cd % _total_size;
		}
		if(_int_keys[cd]==0)
			return -1;
		else
			return cd;
	}

	void insert(int id,valtype& value)
	{
		id=id+1;
		int cd = hashCodeINT(id,_total_size);
		while(_int_keys[cd]!=id && _int_keys[cd]!=0) {
			cd++;
			if(cd>=_total_size)
				cd = cd % _total_size;
		}
		_int_keys[cd] = id;
		_int_values[cd] = value;
	}

	void init(freelist<char>& pool,int size)
	{
		_total_size = size;
		_int_keys = (int*)pool.alloc(size*sizeof(int));
		_int_values = (valtype*)pool.alloc(size*sizeof(valtype));
		if(_int_keys==0)
			printf("map_base::init(%d) crashed!",size);

		memset(_int_keys,0,size*sizeof(int));
		memset(_int_values,0,size*sizeof(valtype));

		_cach_key = -1;
		_none = invalid_node::get();
	}

	int	 _total_size;
	int* _int_keys;
	valtype* _int_values;

	valtype _none;

	inline valtype& value(int idx) { return _int_values[idx];}
	inline int key(int idx) { return _int_keys[idx]-1; }
	inline int size() { return _total_size;}
	valtype& invalid() { return _none; }
};

class int_invalid_node 
{
public:
	static int get() { return -1;}
};

class double_invalid_node 
{
public:
	static double get() { return -1.0;}
};

typedef map_base<int,int_invalid_node>	map_int;
typedef map_base<double,double_invalid_node>	map_double;